package inputs;

import processingHandling.PAppletWrapper;
import management.ApplicationManager;
import management.UpdateManager;
import dataModifiers.Modifier;
import dataModifiers.ModifierFactory;

/**
 * Singleton factory class for creating Inputs.
 * Creating Inputs through this class ensures they are added to the UpdateManager.
 * 
 * @author Dylan James
 *
 */
public class InputFactory {
	private static InputFactory instance;

	private static UpdateManager updateManager;
	private static ApplicationManager appManager;

	private InputFactory()
	{
		updateManager = UpdateManager.getUpdateManager();
		appManager = ApplicationManager.getApplicationManager();
	}

	/**
	 * @return An instances of the Input Factory
	 */
	public static InputFactory getFactory()
	{
		if (instance == null)
		{
			instance = new InputFactory();
		}

		return instance;
	}

	/**
	 * Adds an Input to the update management
	 * @param input Input to add
	 * @param update True if this input should be automatically updated each tick.
	 */
	private void Add(Input input, boolean update)
	{
		updateManager.Add(input, update);
	}
	
	/**
	 * Creates a Color and adds it to the Update Management.
	 * @param value The initial value for the Color.
	 * @param update Whether this Color should be automatically updated each tick.
	 * @return The created Color.
	 */
	public Color createColor(int value, boolean update)
	{
		Color color = new Color(value);
		Add(color, update);
		return color;
	}
	
	/**
	 * Creates a Color and adds it to the Update Management.
	 * Automatically updates it each tick.
	 * @param value The initial value for the Color.
	 * @return The created Color.
	 */
	public Color createColor(int value)
	{
		return createColor(value, true);
	}
	
	/**
	 * Creates a Constant and adds it to the Update Management.
	 * @param value The initial value for the Constant.
	 * @param update Whether this Constant should be automatically updated each tick.
	 * @return The created Constant.
	 */
	public Constant createConstant(int value, boolean update)
	{
		Constant constant = new Constant(value);
		Add(constant, update);
		return constant;
	}
	
	/**
	 * Creates a Constant and adds it to the Update Management.
	 * Automatically updates it each tick.
	 * @param value The initial value for the Constant.
	 * @return The created Constant.
	 */
	public Constant createConstant(int value)
	{
		return createConstant(value, true);
	}
	
	/**
	 * Creates a Counter and adds it to the Update Management.
	 * @param initialValue The initial value for the counter.
	 * @param update Whether this Counter should be automatically updated each tick.
	 * @return The created Counter.
	 */
	public Counter createCounter(int initialValue, boolean update)
	{
		Counter counter = new Counter(initialValue);
		Add(counter, update);
		return counter;
	}
	
	/**
	 * Creates a Counter and adds it to the Update Management.
	 * Automatically updates it each tick.
	 * @param initialValue The initial value for the counter.
	 * @return The created Counter.
	 */
	public Counter createCounter(int initialValue)
	{
		return createCounter(initialValue, true);
	}
	
	/**
	 * Creates a PixelInput and adds it to the UpdateManagement.
	 * @param x The x position of the pixel to sample.
	 * @param y The y position of the pixel to sample.
	 * @param update Whether this PixelInput should be automatically updated each tick.
	 * @return The created PixelInput.
	 */
	public PixelInput createPixelInput(int x, int y, boolean update)
	{
		PixelInput pixelInput = new PixelInput(appManager.getPApplet(), x, y);
		Add(pixelInput, update);
		return pixelInput;
	}
	
	/**
	 * Creates a PixelInput and adds it to the UpdateManagement.
	 * Automatically updates it each tick.
	 * @param x The x position of the pixel to sample.
	 * @param y The y position of the pixel to sample.
	 * @return The created PixelInput.
	 */
	public PixelInput createPixelInput(int x, int y)
	{
		return createPixelInput(x, y, true);
	}
	
	
	
}
